package org.dwell.urlfilter.demo.filter;

import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.dwell.urlfilter.demo.domain.CoreModule;
import org.dwell.urlfilter.demo.domain.CoreUser;
import org.dwell.urlfilter.demo.test.CoreModuleDB;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by Jange on 2016/4/6.
 */
public class UrlShiroAccessFilter extends AccessControlFilter {
    private static Logger LOG = Logger.getLogger(UrlShiroAccessFilter.class.getName());

    @Override
    protected boolean isAccessAllowed(ServletRequest req, ServletResponse resp, Object mappedValue) throws Exception {
        HttpServletRequest request = (HttpServletRequest)req;
        HttpServletResponse response = (HttpServletResponse)resp;
        String url = request.getRequestURI();
        LOG.debug("preHandle =" + url + " request method = "+request.getMethod());


        Subject user = SecurityUtils.getSubject();
        CoreUser currentUser = (CoreUser)request.getSession().getAttribute("_SESSION_USER_");
        if(!user.isAuthenticated()){

//        }
//        if(currentUser == null){
            forward("很抱歉，需要先登录。", request, response, STATUS_NEED_LOGIN_FIRST);
            return false;
        }

        //如果用户的分组是1，说明是超级用户组，不需要验证权限
        //超级管理员组不需要任何资源的验证，只要登录成功，就能操作一切
//        if(currentUser.getGroupId() != null && currentUser.getGroupId() == 1){
//            return true;
//        }

        //1、验证url权限
        String shiroUrl = getRequestPath(request);
        System.out.println("待验证的url: "+shiroUrl);
        List<CoreModule> resources = CoreModuleDB.getByModuleUrl(shiroUrl);
        if(null == resources || resources.size() == 0) {
            forward("很抱歉，资源[ "+shiroUrl+" ]没有配置，请联系管理员。", request, response, STATUS_RESOURCE_NOT_FOUND);
            return false;
        }
        //	1.2、验证资源是否需要验证。如果要请求的资源无需验证，那么直接返回
        CoreModule res = resources.get(0);
        System.out.println("1.2 res:"+res);

//        if(res.getEnabled() == EnableType..RESOURCE_NO_VALIDATION){
//            System.out.println("--------------------"+shiroUrl);
//            return true;
//        }

        //	1.3、验证当前登录用户对这个url是否有权限操作
        if(user.isPermitted(res.getPermission())){
            LOG.info("xxxxxx "+res.getPermission()+" permitted!");
            return true;
        }else{
            LOG.warn("oooooo " + res.getPermission() + " is not be permitted!");
            String msg = "<span style='color:red;'>没有这个权限。</span><br/>"+"使用功能："+res.getModuleName()+"<br/>请求地址："+res.getModuleUrl()+"<br/>当前用户："+user.getPrincipal().toString();
            forward(msg, request, response, STATUS_NO_PERMISSION);
            return false;
        }
    }

    //转发状态码
    public static final int STATUS_NEED_LOGIN_FIRST = 701;
    public static final int STATUS_RESOURCE_NOT_FOUND = 702;
    public static final int STATUS_NO_PERMISSION = 707;

    private void forward(String msg, HttpServletRequest request, HttpServletResponse response, int type)
            throws IOException {
        System.out.println("forward ~ " + msg);

        //如果是ajax请求，那么直接返回对应的错误信息
        // request from ajax method
        if (request.getHeader("x-requested-with") != null
                && request.getHeader("x-requested-with").equalsIgnoreCase("XMLHttpRequest")) {
            response.setHeader("sessionstatus", "timeout");
            response.setContentType("text/html; charset=UTF-8");
            PrintWriter out = response.getWriter();
            //if(request.getQueryString())

            //对于没有?xxx的Ajax请求，直接打印消息
            if(request.getQueryString() == null){
                out.println(msg);
                out.flush();
                out.close();
                return;
            }

//            if(request.getQueryString().indexOf("type=validform") != -1){
//                if(type == STATUS_RESOURCE_NOT_FOUND){
//                    ValidFormJSON vfjson = new ValidFormJSON();
//                    vfjson.setStatus("n");
//                    vfjson.setInfo("很抱歉，资源不存在！");
//                    out.println(com.alibaba.fastjson.JSON.toJSONString(vfjson));
//                }else if(type == STATUS_NO_PERMISSION){
//                    ValidFormJSON vfjson = new ValidFormJSON();
//                    vfjson.setStatus("n");
//                    vfjson.setInfo("很抱歉，没有权限！");
//                    out.println(com.alibaba.fastjson.JSON.toJSONString(vfjson));
//                }else if(type == STATUS_NEED_LOGIN_FIRST){
//                    ValidFormJSON vfjson = new ValidFormJSON();
//                    vfjson.setStatus("n");
//                    vfjson.setInfo("请先登录！");
//                    out.println(com.alibaba.fastjson.JSON.toJSONString(vfjson));
//                }else{
//                    ValidFormJSON vfjson = new ValidFormJSON();
//                    vfjson.setStatus("n");
//                    vfjson.setInfo("很抱歉，未知错误！");
//                    out.println(com.alibaba.fastjson.JSON.toJSONString(vfjson));
//                }
//            }else{
                out.println(msg);
//            }

            out.flush();
            out.close();
            return;
        }

        //701 未登陆
        if(STATUS_NEED_LOGIN_FIRST == type){
            LOG.debug("response committed ~ " + response.isCommitted());
//            WebUtils.redirectToSavedRequest(request, response, request.getContextPath());
            response.sendRedirect("/");
            return;
        }
        //如果是550错误，那么转向/error/nopermission
        //因为/error/nopermission也找不到，所以继续会重定向到这个，形成循环重定向问题
        if (STATUS_NO_PERMISSION == type) { // no permission
//            response.sendRedirect(request.getContextPath() + "/error/nopermission");

            response.setContentType("text/html; charset=UTF-8");
            PrintWriter out = response.getWriter();
            String shiroUrl = getRequestPath(request);
            out.println("<span style='color:red'>["+shiroUrl+"]您没有这个权限</span>");

            out.flush();
            out.close();

            return;
        }

        //702 资源没有配置
        if(STATUS_RESOURCE_NOT_FOUND == type){
            response.setContentType("text/html; charset=UTF-8");
            PrintWriter out = response.getWriter();
            String shiroUrl = getRequestPath(request);
            out.println("<span style='color:red'>["+shiroUrl+"]资源没有配置</span>");

            out.flush();
            out.close();
            return;
        }

        //如果都不是，转向首页
        response.sendRedirect(request.getContextPath());
    }

    /**
     * 获得请求路径
     *
     * @param request
     * @return
     */
    private String getRequestPath(HttpServletRequest request) {
        String requestPath = request.getRequestURI();
        if(request.getQueryString() != null){

            requestPath += "?" + request.getQueryString();
        }
        if (requestPath.indexOf("&") > -1) {// 去掉其他参数
            requestPath = requestPath.substring(0, requestPath.indexOf("&"));
        }
        requestPath = requestPath.substring(request.getContextPath().length());// 去掉项目路径

        //下面这句代码，是对?id=xx的字符串进行替换，而?edit这种字符串则不替换
        requestPath = regexReplace(requestPath, "[\\?]*([0-9a-zA-Z]*=[0-9a-zA-Z\\-]*)", "");

        return requestPath;
    }

    private String regexReplace(String content,String search,String replacement){
        Pattern p = Pattern.compile(search);
        Matcher m = p.matcher(content);
        String s = m.replaceAll(replacement);
        return s;
    }

    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        return false;
    }
}